using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BoYuanCore.Framework;
using Microsoft.Extensions.DependencyInjection;
using FineUICore;
using BoYuanCore.Framework.MemoryCache;
using BoYuanCore.WebForm.Code;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.FileProviders;
using System.Reflection;
using BoYuanCore.WebForm.Code.Extensions;

namespace BoYuanCore.WebForm
{
    public class Startup
    {
        private readonly IWebHostEnvironment _env;
        public IConfiguration Configuration { get; }
        public Startup(IConfiguration configuration, IWebHostEnvironment env)
        {
            _env = env;
            Configuration = configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();//http对象相关
            //services.AddSingleton(new Appsettings(Path.Combine(AppContext.BaseDirectory, "configs")));//注意使用的bin目录下configs文件夹
            services.AddSingleton(new Appsettings(AppContext.BaseDirectory));

            services.AddMemoryCache();//MemoryCache
            services.AddDistributedMemoryCache();//分布式内存缓存
            services.AddSingleton(typeof(ICachingProvider), typeof(MemoryCaching));

            //services.AddScoped<CustomCookieAuthenticationEvents>();//cookie认证事件注入
            services.AddSession(option =>
            {
                option.IdleTimeout = TimeSpan.FromHours(1); //过期时间
                option.Cookie.HttpOnly = true;
            });

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
            {
                //options.EventsType = typeof(CustomCookieAuthenticationEvents);// cookie认证事件拦截
                options.LoginPath = new PathString(UrlAddress.LoginUrl);//身份验证失败，跳转到指定位置
                options.Cookie.HttpOnly = true;
            });

            // 配置请求参数限制
            services.Configure<FormOptions>(x =>
            {
                x.ValueCountLimit = 1024;   // 请求参数的个数限制（默认值：1024）
                x.ValueLengthLimit = 4194304;   // 单个请求参数值的长度限制（默认值：4194304 = 1024 * 1024 * 4）
            });


            //services.AddFreeSqlSetup();//暂时不用此方式。通过DBServices类库注册FreeSql 
          

            services.AddSession();

            // 配置请求参数限制
            services.Configure<FormOptions>(x =>
            {
                x.ValueCountLimit = 1024;   // 请求参数的个数限制（默认值：1024）
                x.ValueLengthLimit = 4194304;   // 单个请求参数值的长度限制（默认值：4M, 4194304 = 1024 * 1024 * 4）
            });

            // FineUI 服务
            services.AddFineUI(Configuration);

            services.AddRazorPages().AddMvcOptions(options =>
            {
                // 自定义JSON模型绑定（添加到最开始的位置）
                options.ModelBinderProviders.Insert(0, new FineUICore.JsonModelBinderProvider());

                // 自定义WebForms过滤器（仅在启用EnableWebForms时有效）
                options.Filters.Insert(0, new FineUICore.WebFormsFilter());

            }).AddNewtonsoftJson().AddRazorRuntimeCompilation();


            //注入文件管理
            var physicalProvider = _env.ContentRootFileProvider;
            var embeddedProvider = new EmbeddedFileProvider(Assembly.GetEntryAssembly());
            var compositeProvider = new CompositeFileProvider(physicalProvider, embeddedProvider);
            // choose one provider to use for the app and register it
            services.AddSingleton<IFileProvider>(physicalProvider);
            services.AddSingleton<IFileProvider>(embeddedProvider);
            services.AddSingleton<IFileProvider>(compositeProvider);

            FreeSqlSetup.FreeSqlAop();//注册FreeSql Aop
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                //app.UseExceptionHandler("/Error");
            }

            app.UseExceptionHandler(UrlAddress.ErrorUrl);//全局异常拦截
            app.UseStatusCodePagesWithReExecute(UrlAddress.Page404Url);//404页面处理


            app.UseStaticFiles();
            app.UseSession();

            app.UseRouting();

            app.UseAuthentication();//添加认证
            app.UseAuthorization();//使用身份授权 Authorize特性


            // 方法一：FineUI 中间件（确保 UseFineUI 位于 UseEndpoints 的前面）
            // 下载大文件时不使用FineUI中间件（可以提高性能），比如请求 /Home/DownloadFile 时不使用FineUI中间件
            //var excludedURLs = new string[] {
            //    "/Home/DownloadFile",
            //    "/Grid/Excel/ExportToExcel"
            //};
            //app.UseWhen(context => !excludedURLs.Any(url => context.Request.Path.StartsWithSegments(url)), appBuilder =>
            //{
            //    appBuilder.UseFineUI();
            //});


            // [推荐]方法二：FineUI 中间件（确保 UseFineUI 位于 UseEndpoints 的前面）
            // 在 appsettings.json 中定义 ExcludedURLs 参数（不使用 FineUI 中间件的网址列表）
            app.UseFineUI();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
                endpoints.MapFallbackToPage(UrlAddress.LoginUrl); // 设置默认页面
            });
        }
    }
}
